#include <iostream>
#include <memory>
#include <thread>
#include <unordered_map>
#include <exception>
#include <cstdio>

#include "unique_ptr.h"
#include "shared_ptr.h"
#include "weak_ptr.h"

class TestClass
{
public:
    TestClass()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    ~TestClass()
    {
        std::cout << __FUNCTION__ << std::endl;
    }


    void Show()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

#define FUNC_ENTER()   (std::cout << "enter " << __FUNCTION__ << std::endl)
#define FUNC_EXIT()   (std::cout << "exit " << __FUNCTION__ << std::endl)

void func_enter(const char* func_name)
{
    std::cout << "enter " << func_name << std::endl;
}

void func_exit(const char* func_name)
{
    std::cout << "exit " << func_name << std::endl;
}

std::shared_ptr<TestClass> g_ptr;

void get_shared_ptr()
{
    FUNC_ENTER();
    auto ptr = std::make_shared<TestClass>();

    //g_ptr = ptr;
    FUNC_EXIT();
}

void throw_exception(const char* msg)
{
    throw std::invalid_argument(msg);
}


// 使用裸指针
// 1.动态申请的内存需要显示释放
// 2.释放内存之前的代码抛出异常，释放内存的代码不会执行，出现内存泄漏
void use_raw_pointer()
{
    try
    {
        TestClass* ptr = new TestClass();
        throw_exception("Throw exception when use raw pointer");
        ptr->Show();
        delete ptr;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
}

void use_smart_pointer()
{
    try
    {
        //wqc::unique_ptr<TestClass> ptr = wqc::unique_ptr<TestClass>(new TestClass());
        wqc::unique_ptr<TestClass> ptr(new TestClass());
        throw_exception("Throw exception when use smart pointer");
        ptr->Show();
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
}

struct list_node
{
    int _value;
    // wqc::shared_ptr<struct list_node> _next;
    // wqc::shared_ptr<struct list_node> _prev;
    wqc::weak_ptr<struct list_node> _next;
    wqc::weak_ptr<struct list_node> _prev;

    list_node(int value=0):
        _value(value)
    {
        std::cout << "list_node: " << _value << std::endl;
    }
    ~list_node()
    {
        std::cout << "~list_node: " << _value << std::endl;
    }
};

int main(int argc, char** argv)
{
    // static thread_local std::unordered_map<int,std::shared_ptr<TestClass>> mapData;

    // mapData[1] = std::make_shared<TestClass>();
    // mapData[1] = std::make_shared<TestClass>();
    // mapData[3] = std::make_shared<TestClass>();

    // std::unordered_map<int, TestClass*> mapData2;

    // mapData2[0] = new TestClass();
    // mapData2[1] = new TestClass();
    // mapData2[2] = new TestClass();

    // get_shared_ptr();

    // use_raw_pointer();
    // use_smart_pointer();

    // wqc::unique_ptr<TestClass> ptr1 = wqc::unique_ptr<TestClass>(new TestClass());
    // wqc::unique_ptr<TestClass> ptr2 = ptr1;

    // wqc::shared_ptr<TestClass> ptr1 = wqc::shared_ptr<TestClass>(new TestClass());
    // wqc::shared_ptr<TestClass> ptr2 = ptr1;
    // ptr2 = ptr1;

    // wqc::shared_ptr<TestClass> ptr3(new TestClass());
    // ptr3 = ptr1;
    
    wqc::shared_ptr<list_node> n1(new list_node(100));
    wqc::shared_ptr<list_node> n2(new list_node(200));

    std::cout << &n1 << std::endl;
    std::cout << &n2 << std::endl;

    std::cout << n1.reference_count() << std::endl;
    std::cout << n2.reference_count() << std::endl;

    n1->_next = n2;// 会将n2中的引用计数加1
    n2->_next = n1; // 会将n1中的引用计数加1
    
    std::cout << n1.reference_count() << std::endl;
    std::cout << n2.reference_count() << std::endl;

    wqc::shared_ptr<FILE> sp(fopen("a.txt", "w+"), [](FILE* fp){fclose(fp);});

    return 0;
}